# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: yuxuan

import datetime
import json
import os

import numpy as np


class BaseStrategy(object):
  @staticmethod
  def get_multi_feed_subsystem():
    MultiFeedSubsystem = None
    if ('COIN2_FEED_SUBSYSTEM' in os.environ):
      raise RuntimeError("deprecated")
    if MultiFeedSubsystem is None:
      import coin.strategy.mm.base.multi_feed_subsystem as mfs
      MultiFeedSubsystem = mfs.MultiFeedSubsystem
    return MultiFeedSubsystem

  @staticmethod
  def get_config_key(product):
    key = product.subscription_symbol
    if product.exchange == 'Huobi' and product.product_type == 'Futures':
      key = key.replace('CURRENT', 'THIS')
      key = key.replace('THIS_QUARTER', 'QUARTER')
    return key

  @staticmethod
  def update_sub_config(config):
    exchange = config['exchange']
    market_type = config['market_type']
    if exchange == 'Binance' and market_type == 'Spot':
      if 'api_version' not in config:
        config['api_version'] = 'snapshot'
    return config

  @staticmethod
  def read_maintenance_as_json(maintenance_file, exchanges):
    if not os.path.exists(maintenance_file):
      return []
    exchanges = set(exchanges)
    with open(maintenance_file, 'r') as fi:
      data = json.load(fi)
      schedules = []
      for exchange in exchanges:
        aschedules = data.get(exchange, [])
        for schedule in aschedules:
          schedule['exchange'] = exchange
          schedule['start'] = datetime.datetime.strptime(schedule['start'], '%Y%m%d %H:%M:%S')
          schedule['end'] = datetime.datetime.strptime(schedule['end'], '%Y%m%d %H:%M:%S')
        schedules += aschedules
      return schedules

  @staticmethod
  def check_maintenance(schedules, product, real_time):
    run_size = 1.0
    for schedule in schedules:
      if schedule['exchange'] == product.exchange \
          and schedule['symbol'] == product.subscription_symbol:
        if real_time < schedule['end']:
          if real_time > schedule['start'] - datetime.timedelta(minutes=5):
            run_size = 0.2
          elif real_time > schedule['start'] - datetime.timedelta(minutes=20):
            run_size = 0.5
          if not np.isclose(run_size, 1):
            break
    return run_size

  # Rollover time Friday 8am UTC.
  # Weekly reference price:
  #   0.5 scale > 06:00am
  #   0.2 scale > 06:45am
  #   0.1 scale > 07:10am
  #   0.1 scale < 08:05am
  # Quarter reference price:
  #   0.5 scale > 07:45am
  #   0.2 scale > 07:55am
  #   0.2 scale < 08:05am
  @staticmethod
  def check_rollover(ref_weekly, ref_quarter, real_time):
    weekday = real_time.weekday()
    if weekday != 4:
      return 1
    hour = real_time.hour
    minute = real_time.minute
    run_size = 1.0
    if ref_weekly:
      if hour == 8:
        if minute < 5:
          run_size = 0.1
        else:
          run_size = 1.0
      elif hour == 7:
        if minute >= 10:
          run_size = 0.1
        else:
          run_size = 0.2
      elif hour == 6:
        if minute >= 45:
          run_size = 0.2
        else:
          run_size = 0.5
      else:
        run_size = 1.0
    elif ref_quarter:
      if hour == 8:
        if minute < 5:
          run_size = 0.2
        else:
          run_size = 1.0
      elif hour == 7:
        if minute >= 55:
          run_size = 0.2
        elif minute >= 45:
          run_size = 0.5
        else:
          run_size = 1.0
      else:
        run_size = 1.0
    return run_size
